@file:JvmName("FileDownUtils")

package com.yl.androidutilscenter.utils

import android.Manifest
import android.app.Activity
import android.app.DownloadManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.Settings
import androidx.core.app.ActivityCompat
import androidx.core.content.FileProvider
import com.yl.androidutilscenter.base.BaseApplication
import com.yl.androidutilscenter.http.upordownload.DownError
import com.yl.androidutilscenter.http.upordownload.DownLoadResult
import com.yl.androidutilscenter.http.upordownload.DownProgress
import com.yl.androidutilscenter.http.upordownload.DownloadSuccess
import com.yl.androidutilscenter.http.upordownload.fold
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import okhttp3.ResponseBody
import java.io.BufferedInputStream
import java.io.File
import java.io.FileOutputStream

/**
 * @author YL
 * @description: 文件下载
 * @date :2024/4/3
 * @version 1.0.0
 */
object FileDownUtils {
    //<editor-fold desc="下载文件，需要在子线程或者协程（IO）中调用">
    /**
     * 下载文件，需要在子线程或者协程（IO）中调用
     * @param file 下载后的文件
     */
    @JvmStatic
    suspend fun downLoadFile(
        file: File,
        responseBody: ResponseBody,
        downError: DownError,
        downProgress: DownProgress,
        downloadSuccess: DownloadSuccess
    ) {

        flow {
            try {
                val contentLength = responseBody.contentLength()
                val inputStream = responseBody.byteStream()
                val outputStream = FileOutputStream(file)
                var currentLength = 0
                val bufferSize = 1024 * 8
                val buffer = ByteArray(bufferSize)
                val bufferedInputStream = BufferedInputStream(inputStream, bufferSize)
                var readLength: Int
                while (bufferedInputStream.read(buffer, 0, bufferSize)
                        .also { readLength = it } != -1
                ) {
                    outputStream.write(buffer, 0, readLength)
                    currentLength += readLength
                    emit(
                        DownLoadResult.progress(
                            currentLength.toLong(),
                            contentLength,
                            currentLength.toFloat() / contentLength.toFloat()
                        )
                    )
                }
                bufferedInputStream.close()
                outputStream.close()
                inputStream.close()
                emit(DownLoadResult.success(file))
            } catch (e: Exception) {
                emit(DownLoadResult.failure(e))
            }
        }.flowOn(Dispatchers.IO)
            .collect {
                it.fold(onFailure = { e ->
                    e?.let { it1 ->
                        downError(it1)
                        if (file.exists()) {
                            file.delete()
                        }
                    }
                }, onSuccess = { file ->
                    downloadSuccess(file)
                }, onLoading = { progress ->
                    downProgress(progress.currentLength, progress.length, progress.process)
                })
            }
    }
    //</editor-fold>


    //<editor-fold desc="在后台下载文件">
    fun downLoadFileOnBackground(
        context: Context,
        downTitle: String,
        downDescription: String,
        fileUrl: String,
        fileName: String
    ): Long {
        LogUtils.i("文件路径：${fileName}")
        val request = DownloadManager.Request(Uri.parse(fileUrl))
        //下载中和下载完后都显示通知栏
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
        //使用系统默认的下载路径 此处为应用内 /android/data/packages ,所以兼容7.0
        LogUtils.i("path:====>${Environment.DIRECTORY_DOWNLOADS}")
        request.setDestinationInExternalFilesDir(
            context,
            Environment.DIRECTORY_DOWNLOADS,
            fileName
        )
        //通知栏标题
        request.setTitle(downTitle)
        //通知栏描述信息
        request.setDescription(downDescription)
        //设置类型为.apk
        request.setMimeType("application/vnd.android.package-archive");
        //获取下载任务ID
        val dm = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
        return dm.enqueue(request)
    }
    //</editor-fold>


    //<editor-fold desc="下载前先移除前一个任务，防止重复下载">
    /**
     * 下载前先移除前一个任务，防止重复下载
     *
     * @param downloadId
     */
    fun clearCurrentTask(context: Context, downloadId: Long) {
        val dm = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
        try {
            dm.remove(downloadId)
        } catch (ex: IllegalArgumentException) {
            ex.printStackTrace()
        }
    }
    //</editor-fold>


    //<editor-fold desc=" apk文件下载完成，进行安装，前提是有安装权限：安装未知来源权限、安装权限">
    /**
     * file 和 fileUri必须有一个！=null
     */
    fun installApkFile(context: Context, file: File?, fileUri: Uri?) {
        if (file == null && fileUri == null) {
            return
        }
        //打开安装界面
        val intent = Intent(Intent.ACTION_VIEW)
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        if (file != null) {
            if (file.name.endsWith(".apk")) {
                val apkUri =
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                        intent.addFlags(
                            Intent.FLAG_GRANT_READ_URI_PERMISSION
                        )
                        FileProvider.getUriForFile(
                            context,
                            context.packageName + ".fileProvider",
                            file
                        )
                    } else {
                        Uri.fromFile(file)
                    }
                intent.setDataAndType(apkUri, "application/vnd.android.package-archive")
            }
        } else {
            intent.setDataAndType(fileUri, "application/vnd.android.package-archive")
        }
        context.startActivity(intent)

    }
    //</editor-fold>


    //<editor-fold desc="是否允许安装未知应用">
    fun isCanInstallUnKnowSource(): Boolean {
        val isCanInstallSource = if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
            BaseApplication.getInstance().packageManager.canRequestPackageInstalls()
        } else true
        return isCanInstallSource
    }
    //</editor-fold>


    //<editor-fold desc="请求获取安装未知来源应用">
    fun requestInstallUnKnowSource(context: Context) {
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
            val uri = Uri.parse("package:${context.packageName}")
            val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, uri)
            context.startActivity(intent)
        }
    }
    //</editor-fold>


    //<editor-fold desc="是否允许安装">
    /**
     * 是否允许安装
     */
    fun isCanInstall(activity: Activity): Boolean {
        val result = ActivityCompat.checkSelfPermission(
            activity,
            android.Manifest.permission.INSTALL_PACKAGES
        )
        return result == PackageManager.PERMISSION_GRANTED
    }
    //</editor-fold>


    //<editor-fold desc="请求获取安装权限">
    /**
     * 请求获取安装权限
     */
    fun requestInstallPermission(activity: Activity, requestCode: Int = 10) {
        ActivityCompat.requestPermissions(
            activity,
            arrayOf(android.Manifest.permission.INSTALL_PACKAGES),
            requestCode
        )
    }
    //</editor-fold>

    fun downLoadAndInstallApk(activity:Activity,downLoadUrl:String){
        //检查是否有文件写入权限和安装权限，入股没有就去申请权限
        var result = false
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
            result = PermissionsUtils.check(activity,Manifest.permission.INSTALL_PACKAGES)
        }else{

        }
        PermissionsUtils.check(activity,Manifest.permission.WRITE_EXTERNAL_STORAGE)
        //开始下载文件

        //下载成功后安装文件
    }


}